package com.xxl.job.xxljob;

import com.alibaba.fastjson.JSONObject;
import com.xxl.job.feign.XxlJobAdminRpc;
import com.xxl.job.feign.domain.XXlJobGroupPage;
import com.xxl.job.feign.domain.XxlJobGroup;
import com.xxl.job.xxljob.domain.XxlJobTokenInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * @author Tang
 * @classname TokenManager
 * @description [ 获取token ]
 * @date 2023/4/5 16:52
 */
@Slf4j
public class TokenManager implements SmartInitializingSingleton, InitializingBean {

    @Resource
    XxlJobAdminRpc xxlJobAdminRpc;

    @Resource
    XxlJobProperties xxlJobProperties;

    public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors() + 1,
            Executors.defaultThreadFactory()
    );

    @Override
    public void afterSingletonsInstantiated() {
        // 线程池定时启动
        executor.scheduleAtFixedRate(this::createToken, 0, 90, TimeUnit.MINUTES);
    }

    @Override
    public void afterPropertiesSet() {
        createToken();
    }

    public void createToken() {
        // 1.获取token
        feign.Response response = xxlJobAdminRpc.login(xxlJobProperties.getUserName(), xxlJobProperties.getPassword());
        if (response.status() == 200) {
            String token = Optional.ofNullable(response.headers().get("Set-Cookie"))
                    .map(cookies -> cookies.toArray(new String[]{}))
                    .map(array -> array[0])
                    .map(item -> item.split(";")[0])
                    .map(item -> item.split("=")[1])
                    .orElse(null);
            setToken(token);
            log.info("token 加载成功！！！");

            // 2.获取执行器id
            final XXlJobGroupPage xXlJobGroupPage = new XXlJobGroupPage(0,100,xxlJobProperties.getAppName());
            final Map<String, Object> pageList = xxlJobAdminRpc.jobGrouPageList(xXlJobGroupPage);

            final Integer executorId = Optional.ofNullable(pageList.get("data"))
                    .map(JSONObject::toJSONString)
                    .map(json -> JSONObject.parseArray(json, XxlJobGroup.class))
                    .map(list -> list.stream().filter(item -> item.getAppname().equals(xxlJobProperties.getAppName())).findFirst())
                    .flatMap(Function.identity())
                    .map(XxlJobGroup::getId)
                    .orElse(null);
            setExecutorId(executorId);
            log.info("执行器 加载成功！！！");
            return;
        }
        log.error("token 加载失败！！！定时任务注册失败！！");
    }

    private static void setToken(String token) {
        XxlJobTokenInfo.getInstance().setToken(token);
    }

    public void setExecutorId(Integer executorId) {
        XxlJobTokenInfo.getInstance().setJobGroupId(executorId);
    }
}
